import utils
import re
import random
import time
import json
import requests
from scan import Scan
from login import OneClickLogin
from urllib3.exceptions import InsecureRequestWarning
# 禁用安全请求警告
requests.urllib3.disable_warnings(InsecureRequestWarning)
import datetime

today = datetime.date.today()  # 今天
yest = today - datetime.timedelta(days=1)
before_yest = today - datetime.timedelta(days=2)
before_yesterday = str(before_yest).replace('-', '')
yesterday = str(yest).replace('-', '')

# 昨天开始时间戳
yesterday_start_time = int(time.mktime(time.strptime(str(yest), '%Y-%m-%d')))

# 昨天结束时间戳
yesterday_end_time = int(time.mktime(time.strptime(str(today), '%Y-%m-%d'))) - 1

# 前天开始时间戳
before_yesterday_start_time = int(time.mktime(time.strptime(str(before_yest), '%Y-%m-%d')))

aa = []
for i in range(1,32):
    date_time = today - datetime.timedelta(days=i)
    if str(date_time)[8:] == "01":
        aa.append(str(date_time))
        break
    else:
        aa.append(str(date_time))


header = {
    "User-Agent": "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.81 Safari/537.36",
    "X-Requested-With": "XMLHttpRequest"
}


class WeChatClient:
    def __init__(self, login_service, url='https://mp.weixin.qq.com'):
        """
        通过moka登录接口获取公众号后台资料
        :param OneClickLogin login_service:
        """
        self.url = url
        self.login = login_service
        self.session = utils.requests_retry_session()
        self.gh_id = None
        self.gh_nickname = None
        self.token = None
        self.index_url = None
        self.index_response = None
        self.violation_list = []


    def log_line(self, msg, gh_nickname=None, gh_id=None):
        line = '[{}]({}) {}'.format(gh_nickname if gh_nickname else self.gh_nickname,
                                    gh_id if gh_id else self.gh_id, msg)
        print(line)
        return line

    def log_err(self, err, logtype='log', gh_nickname=None, gh_id=None):
        utils.log_error(self.log_line(err, gh_nickname, gh_id), logtype)

    def debug_log(self, err, logtype='debug', gh_nickname=None, gh_id=None):
        utils.log_error(self.log_line(err, gh_nickname, gh_id), logtype)
        print(err)

    def enter(self, gh_id, gh_nickname, pwd):
        scan = Scan(self.session)
        self.token = scan.get_session_with_cookie(gh_id, pwd)
        try:
            info = {"nickname": gh_nickname,
                    "gh_id": gh_id,
                    "pwd": ''
                    }
            with utils.open_write_data_file(gh_id, 'basic.json', utils.get_yesterday()) as f:
                json.dump(info, f)
        except:
            pass
        try:
            response = self.session.get(url=self.url, verify = False)
            self.index_url = str(response.url)
            try:
                token = re.findall('token=(\\d+)', self.index_url)[0]
            except IndexError:
                self.log_err('微信后台登录失败，检查Cookie是否有效',
                             gh_nickname=gh_nickname, gh_id=gh_id)
                return False
            self.gh_id = gh_id
            self.gh_nickname = gh_nickname
            self.token = token
            self.index_response = response.content.decode('utf-8')
            self.log_line('后台登录成功，Token={}'.format(token))
            return True
        except Exception as e:
            print(e)
            return False

    def save_data(self, data_file, data_date, data):
        with utils.open_write_data_file(self.gh_id, data_file, data_date) as f:
            json.dump(data, f)

    def detect_or_save(self, data_file, data_name, data_date, func, skip_exist=True, verbose=True):
        if skip_exist and utils.has_data_file(self.gh_id, data_file, data_date):
            if verbose:
                self.log_line('已存在{} {}，跳过'.format(data_date,data_name))
        else:
            if verbose:
                self.log_line('开始获取{} {}'.format(data_date,data_name))
            data = func(data_date)
            if data:
                if verbose:
                    self.log_line('获取{} {}成功'.format(data_date,data_name))
                self.save_data(data_file, data_date, data)
            else:
                self.log_err('获取{} {}失败,请重试,或单独爬取'.format(data_date,data_name))

    def save_basic_info(self, account, date):
        self.save_data('basic.json', date, account)

    def get_third_url(self, date):
        Cumulative_number = active_users = new_registered_users = Shared_Users = New_User_Retention = ""
        resp = self.session.get(
            '{0}/wxopen/frame?plugin_uin=1002&token={1}&lang=zh_CN&f=json&ajax=1'
            '&random={2}&action=plugin_redirect&plugin_uin=1002&type=1'.format(
                self.url, self.token, random.random()), verify=False
        )
        try:
            data = resp.json()
            referer = str(data["plugin_login_info"]["third_url"]).replace('type=1','type=3')
            appid = re.findall('appid=(.*?)&openid',referer)[0]
            openid = re.findall('openid=(.*?)&plugin_token',referer)[0]
            plugin_token = re.findall('plugin_token=(.*?)&lang',referer)[0]
            plugin_id = "game"
            aa = requests.session().post(
                'https://game.weixin.qq.com/cgi-bin/gamewxagdatawap/mpadminlogin?uin=&key=&pass_ticket=&QB&',
                json={
                    "appid" : appid,
                    "openid" : openid,
                    "plugin_id" : plugin_id,
                    "plugin_token" : plugin_token
                }, verify=False
            )
            mp_session = re.findall('mp_session=(.*?);',str(aa.headers["Set-Cookie"]))[0]
            cookie = {
                "mp_session" :mp_session
            }
            riqi = str(datetime.datetime.strptime(date,'%Y-%m-%d')-datetime.timedelta(days=1))[:10]
            result = self.session.post(
                'https://game.weixin.qq.com/cgi-bin/gamewxagdatawap/getwxagstat?uin=&key=&pass_ticket=&QB&',
                json= {"appid":appid,
                 "summary_index_list":[],
                 "detail_index_list":[
                                      {"in":"detail","size_type":24,"stat_type":19,
                                       "time_period":{"start_time":int(time.mktime(time.strptime(str(date),'%Y-%m-%d'))),"duration_seconds":86400}},
                                      {"in":"detail","size_type":24,"stat_type":1,
                                       "time_period":{"start_time":int(time.mktime(time.strptime(str(date),'%Y-%m-%d'))),"duration_seconds":86400}},
                                      {"in":"detail","size_type":24,"stat_type":2,
                                       "time_period":{"start_time":int(time.mktime(time.strptime(str(date),'%Y-%m-%d'))),"duration_seconds":86400}},
                                      {"in":"detail","size_type":24,"stat_type":6,
                                       "time_period":{"start_time":int(time.mktime(time.strptime(str(date),'%Y-%m-%d'))),"duration_seconds":86400}},
                                      {"in": "detail", "size_type": 24, "stat_type":12,
                                       "time_period":{"start_time":int(time.mktime(
                                           time.strptime(str(riqi),'%Y-%m-%d'))),
                                           "duration_seconds":172800}}
                 ],
                 "auth_type":8},
                headers={
                    "User-Agent": "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.81 Safari/537.36",
                    "Referer": referer,
                    "Host": "game.weixin.qq.com"}, cookies=cookie, verify=False)
            try:
                data = result.json()
                if data["errmsg"] == "ok":
                    try:
                        for y in range(len(data["data"]["detail_list"])):
                            if data["data"]["detail_list"][y]["index"]["stat_type"] == 19:
                                Cumulative_number = data["data"]["detail_list"][y]["point_list"][0]["value"]
                            if data["data"]["detail_list"][y]["index"]["stat_type"] == 1:
                                active_users = data["data"]["detail_list"][y]["point_list"][0]["value"]
                            if data["data"]["detail_list"][y]["index"]["stat_type"] == 2:
                                new_registered_users = data["data"]["detail_list"][y]["point_list"][0]["value"]
                            if data["data"]["detail_list"][y]["index"]["stat_type"] == 6:
                                Shared_Users = data["data"]["detail_list"][y]["point_list"][0]["value"]
                            if data["data"]["detail_list"][y]["index"]["stat_type"] == 12:
                                New_User_Retention = data["data"]["detail_list"][y]["point_list"][0]["value"] / 100
                    except (KeyError, ValueError, TypeError, IndexError, ZeroDivisionError):
                        self.debug_log(data)
            except (KeyError, ValueError, TypeError, IndexError, ZeroDivisionError):
                self.debug_log(result.content)
        except (KeyError, ValueError, TypeError, AttributeError, IndexError, ZeroDivisionError):
            self.debug_log(resp.content)
        return {"Cumulative_number":Cumulative_number ,"active_users":active_users,
                "new_registered_users":new_registered_users, "Shared_Users":Shared_Users,
                "New_User_Retention":New_User_Retention}

    def save_publish_info(self, date):
        Exposure = click = income = ""
        income1 = income2 = Exposure1 = Exposure2 = click1 = click2 = 0
        resp = self.session.get(
            '{0}/wxopen/weapp_publisher_stat?action=stat&page=1&page_size=90&start={1}&end={2}&pos_type=5'
            '&token={3}&appid=&spid=&_={4}'.format(
                self.url, int(time.mktime(time.strptime(str(date), '%Y-%m-%d'))),
                int(time.mktime(time.strptime(str(date), '%Y-%m-%d'))), self.token,
                int(round(time.time()) * 1000)), headers=header, verify=False
        )
        try:
            data = resp.json()
            if data["base_resp"]["ret"] == 0:
                Exposure1 = data["cost_list"]["cost"][0]["view_count"]
                click1 = data["cost_list"]["cost"][0]["click_count"]
                income1 = data["cost_list"]["cost"][0]["cost"] / 100
        except (KeyError, ValueError, TypeError, IndexError, ZeroDivisionError):
            self.debug_log(resp.content)
        result = self.session.get(
            '{0}/wxopen/weapp_publisher_stat?action=stat&page=1&page_size=90&start={1}&end={2}&pos_type=6'
            '&token={3}&appid=&spid=&_={4}'.format(
                self.url, int(time.mktime(time.strptime(str(date), '%Y-%m-%d'))),
                int(time.mktime(time.strptime(str(date), '%Y-%m-%d'))), self.token,
                int(round(time.time()) * 1000)), headers=header, verify=False
        )
        try:
            data = result.json()
            if data["base_resp"]["ret"] == 0:
                Exposure2 = data["cost_list"]["cost"][0]["view_count"]
                click2 = data["cost_list"]["cost"][0]["click_count"]
                income2 = data["cost_list"]["cost"][0]["cost"] / 100
            Exposure = Exposure1 + Exposure2
            click = click1 + click2
            income = income1 + income2
        except (KeyError, ValueError, TypeError, IndexError, ZeroDivisionError):
            self.debug_log(result.content)
        return {"Exposure": Exposure, "click": click, "income": income}


def collect(login_service, account, data_date=None):
    if not data_date:
        data_date = utils.get_yesterday()
    srv = WeChatClient(login_service)
    if not srv.enter(account['gh_id'], account['nickname'], account['pwd']):
        return
    for a in aa:
        srv.save_basic_info(account, data_date)
        srv.detect_or_save('app-game-info-users.json', '累计信息', a,
                           srv.get_third_url)
        srv.detect_or_save('app-publish-info.json', '流量主数据', a,
                           srv.save_publish_info)

def test_collect(date):
    library = utils.default_library()
    account_list = library.get_account_list()
    if account_list:
        login_srv = None
        for gh_id in account_list:
            account = library.get_account_data(gh_id)
            collect(login_srv, account, date)
    else:
        print('账号列表为空，退出')